﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using NetTopologySuite.Algorithm;
using NetTopologySuite.Geometries;
using NetTopologySuite.Geometries.Implementation;
using NetTopologySuite.IO;

namespace NetTopologySuite.Noding
{
	public class NodedSegmentString : INodableSegmentString, ISegmentString
	{
		public static IList<ISegmentString> GetNodedSubstrings(IList<ISegmentString> segStrings)
		{
			IList<ISegmentString> list = new List<ISegmentString>();
			NodedSegmentString.GetNodedSubstrings(segStrings, list);
			return list;
		}

		public static void GetNodedSubstrings(IList<ISegmentString> segStrings, IList<ISegmentString> resultEdgelist)
		{
			foreach (ISegmentString segmentString in segStrings)
			{
				((NodedSegmentString)segmentString).NodeList.AddSplitEdges(resultEdgelist);
			}
		}

		public NodedSegmentString(Coordinate[] pts, object data)
		{
			this._nodeList = new SegmentNodeList(this);
			this._pts = pts;
			this.Context = data;
		}

		public object Context { get; set; }

		public SegmentNodeList NodeList
		{
			get
			{
				return this._nodeList;
			}
		}

		public int Count
		{
			get
			{
				return this._pts.Length;
			}
		}

		public Coordinate GetCoordinate(int i)
		{
			return this._pts[i];
		}

		public Coordinate[] Coordinates
		{
			get
			{
				return this._pts;
			}
		}

		public bool IsClosed
		{
			get
			{
				return this._pts[0].Equals2D(this._pts[this._pts.Length - 1]);
			}
		}

		public Octants GetSegmentOctant(int index)
		{
			if (index != this._pts.Length - 1)
			{
				return NodedSegmentString.SafeOctant(this.GetCoordinate(index), this.GetCoordinate(index + 1));
			}
			return Octants.Null;
		}

		private static Octants SafeOctant(Coordinate p0, Coordinate p1)
		{
			if (p0.Equals2D(p1))
			{
				return Octants.Zero;
			}
			return Octant.GetOctant(p0, p1);
		}

		public void AddIntersections(LineIntersector li, int segmentIndex, int geomIndex)
		{
			for (int i = 0; i < li.IntersectionNum; i++)
			{
				this.AddIntersection(li, segmentIndex, geomIndex, i);
			}
		}

		public void AddIntersection(LineIntersector li, int segmentIndex, int geomIndex, int intIndex)
		{
			Coordinate intPt = new Coordinate(li.GetIntersection(intIndex));
			this.AddIntersection(intPt, segmentIndex);
		}

		public void AddIntersection(Coordinate intPt, int segmentIndex)
		{
			int num = segmentIndex;
			int num2 = num + 1;
			if (num2 < this._pts.Length)
			{
				Coordinate other = this._pts[num2];
				if (intPt.Equals2D(other))
				{
					num = num2;
				}
			}
			this._nodeList.Add(intPt, num);
		}

		public LineSegment this[int index]
		{
			get
			{
				if (index < 0 || index >= this.Count)
				{
					throw new ArgumentOutOfRangeException("index", index, "Parameter must be greater than or equal to 0 and less than TotalItemCount.");
				}
				return new LineSegment(this._pts[index], this._pts[index + 1]);
			}
			set
			{
				throw new NotSupportedException("Setting line segments in a ISegmentString not supported.");
			}
		}

		public override string ToString()
		{
			return WKTWriter.ToLineString(new CoordinateArraySequence(this._pts));
		}

		private readonly SegmentNodeList _nodeList;

		private readonly Coordinate[] _pts;
	}
}
